﻿using System;
using System.Collections.Generic;
using System.Text;
using Studio.Foundation.Json.Core;

namespace Studio.Foundation.Json
{

    /// <summary>
    /// The non-generic one
    /// </summary>
    public class ResponseEntity : ResponseEntity<object>
    {
        public ResponseEntity() : base() { }
        public ResponseEntity(int errno, string error) : base(errno, error) { }
    }

    public class ResponseEntity<T> : IJsonObject, IList<T>
    {
        public static readonly int SUCCEED = 0;

        // public static readonly ResponseEntity<T> SUCCEED_ENTITY = new ResponseEntity<T>();

        /// <summary>
        /// Error No. 0 : succeed. positive : error numbers. negitive: exception
        /// </summary>
        public int errno;

        /// <summary>
        /// Error message
        /// </summary>
        public string error;

        /// <summary>
        /// Response Entites
        /// </summary>
        public IList<T> entities;

        public int total;

        public string nextToken;

        /// <summary>
        /// Default Constructor
        /// </summary>
        public ResponseEntity()
        {
            this.Initialize(0, "Succeed.");
        }

        /// <summary>
        /// Constructor with Parameters
        /// </summary>
        public ResponseEntity(int errno, string error)
        {
            this.Initialize(errno, error);
        }

        internal void Initialize(int errno, string error)
        {
            this.errno = errno;
            this.error = error;
            this.total = 0;
            this.entities = new List<T>();
        }

        /// <summary>
        /// Create a ResponseEntity with ex.Message and InnerMessage
        /// </summary>
        public static ResponseEntity<T> CreateExceptionResponse(Exception ex)
        {
            string message = ex.Message;
            if (null != ex.InnerException) message = string.Format("{0}/{1}", message, ex.InnerException.Message);
            return new ResponseEntity<T>(-1, message);
        }

        /// <summary>
        /// Add a range
        /// </summary>
        /// <param name="array"></param>
        public void AddEntities(IEnumerable<T> array)
        {
            foreach (T e in array) this.entities.Add(e);
        }

        public bool Successful
        {
            get { return this.errno == ResponseEntity.SUCCEED; }
        }

        #region IEnumerable

        public IEnumerator<T> GetEnumerator()
        {
            return this.entities.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this.entities.GetEnumerator();
        }

        #endregion

        public int IndexOf(T item)
        {
            return this.entities.IndexOf(item);
        }

        public void Insert(int index, T item)
        {
            this.entities.Insert(index, item);
        }

        public void RemoveAt(int index)
        {
            this.RemoveAt(index);
        }

        public T this[int index]
        {
            get
            {
                return this.entities[index];
            }
            set
            {
                this.entities[index] = value;
            }
        }

        public void Add(T item)
        {
            this.entities.Add(item);
        }

        public void Clear()
        {
            this.entities.Clear();
        }

        public bool Contains(T item)
        {
            return this.entities.Contains(item);
        }

        public void CopyTo(T[] array, int arrayIndex)
        {
            this.entities.CopyTo(array, arrayIndex);
        }

        public int Count
        {
            get { return this.entities.Count; }
        }

        public bool IsReadOnly
        {
            get { return this.entities.IsReadOnly; }
        }

        public bool Remove(T item)
        {
            return this.entities.Remove(item);
        }
    }
}
